package com.flightgame.services;

import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.flightgame.hibernate.Airport;
import com.flightgame.hibernate.AirportDao;
import com.flightgame.hibernate.Flight;
import com.flightgame.hibernate.FlightDao;
import com.flightgame.hibernate.Item;
import com.flightgame.hibernate.ItemDao;
import com.flightgame.hibernate.Message;
import com.flightgame.hibernate.MessageDao;
import com.flightgame.hibernate.Ownership;
import com.flightgame.hibernate.OwnershipDao;
import com.flightgame.hibernate.User;
import com.flightgame.hibernate.UserDao;
import com.flightgame.tools.Utils;

@Service
public class JSONServices {
	
	@Autowired
	private AirportDao airportDao;
	@Autowired
	private OwnershipDao ownershipDao;
	@Autowired
	private FlightDao flightDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private ItemDao itemDao;
	@Autowired
	private FlightServices flightServices;
	@Autowired
	private GameServices gameServices;
	@Autowired
	private Utils utils;
	@Autowired
	private MessageDao messageDao;
	
	
	
	public JSONObject getSuccess(boolean result,String errorMess,JSONObject additionalJSON){
		JSONObject json = new JSONObject();
		
		try {
			json.put("success",String.valueOf(result));
			if(result == false) json.put("mess",errorMess);
			else{
				if(additionalJSON != null) json.put("params",additionalJSON);
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
		return json;
	}

	// Airports
	
	public JSONObject getAirports(){
		List<Airport> airports = airportDao.getAirports();
		
		return airportsJson(airports);
	}
	

	public JSONObject getAirportsOnBoundedCoordinates(String lat1,String lat2,String lon1,String lon2){
		try {
			List<Airport> airports = airportDao.getAirportsOnBoundedCoordinates(Double.parseDouble(lat1), Double.parseDouble(lat2),Double.parseDouble(lon1),Double.parseDouble(lon2));
			Utils utils = new Utils();

			if(utils.isCoordinatesValid(Double.parseDouble(lat1),Double.parseDouble(lat2),Double.parseDouble(lon1),Double.parseDouble(lon2))) return airportsJson(airports);
			else return getSuccess(false,"Invalid Coordinate Input!",null);
			
        } catch (NumberFormatException ex) {
            return getSuccess(false,utils.getMessage(utils.INVALID_NUMBER_FORMAT),null);
        }

	}
	
	// Flights
	
	public JSONObject getFlightsOnBoundedCoordinates(String lat1,String lat2,String lon1,String lon2){
		List<Flight> flights;
		try {
			flights = flightDao.getFlightsOnBoundedCoordinates(Double.parseDouble(lat1), Double.parseDouble(lat2),Double.parseDouble(lon1),Double.parseDouble(lon2));
        } catch (NumberFormatException ex) {
            return getSuccess(false,utils.getMessage(utils.INVALID_NUMBER_FORMAT),null);
        }

		Utils utils = new Utils();

		
		if(utils.isCoordinatesValid(Double.parseDouble(lat1), Double.parseDouble(lat2),Double.parseDouble(lon1),Double.parseDouble(lon2))){
			JSONArray flightsArray = new JSONArray();
			JSONObject flightsJson = new JSONObject();
			try {
				for(Flight flight: flights){
					JSONObject json = new JSONObject();
					json.put("id", flight.getId());
					json.put("username",flight.getUserName());
					json.put("aircraftname",flight.getAircraftName());
					json.put("lat",flight.getLat());
					json.put("lon",flight.getLon());
					json.put("hist",flight.getLatlonHistory());
					json.put("alt",flight.getAltitude());
					json.put("ownershipid",flight.getOwnershipId());
					flightsArray.put(json);
				}
				flightsJson.put("flights",flightsArray);
			} catch (Exception e) {
				
			}
			return flightsJson;
		}
		else return getSuccess(false,"Invalid Coordinate Input!",null);
		
	}
	
	public JSONObject getFlightHistory(int ownershipId){
		Flight flight = flightDao.getUserFlight(ownershipId);
		Utils utils = new Utils();
		
		if(flight == null) return getSuccess(false, utils.getMessage(utils.NO_OWNERSHIP_WITH_ID),null);
		
		String latLonHistory = flight.getLatlonHistory();
		
		JSONArray histArray = new JSONArray();
		JSONObject historyJson = new JSONObject();
		
		if(latLonHistory != null){
			List<String> history = utils.tokenizeCommaString(latLonHistory);
			try {
				JSONObject json = new JSONObject();
				json.put("lat", history.get(0));
				json.put("lon", history.get(1));
				json.put("alt", history.get(2));
				
				histArray.put(json);
				historyJson.put("history",histArray);
			} catch (Exception e) {
				
			}
		}
		return historyJson;
		
	}
	
	// Ownerships
	
	public JSONObject getOwnershipsOnBoundedCoordinates(String lat1,String lat2,String lon1,String lon2){
		
		try {
			List<Ownership> ownerships = ownershipDao.getOwnershipsOnBoundedCoordinates(Double.parseDouble(lat1), Double.parseDouble(lat2),Double.parseDouble(lon1),Double.parseDouble(lon2));
			Utils utils = new Utils();
			if(utils.isCoordinatesValid(Double.parseDouble(lat1), Double.parseDouble(lat2),Double.parseDouble(lon1),Double.parseDouble(lon2))) return ownershipJson(ownerships);
			else return getSuccess(false,"Invalid Coordinate Input!",null);
		} catch (NumberFormatException ex) {
            return getSuccess(false,utils.getMessage(utils.INVALID_NUMBER_FORMAT),null);
        }

	}
	
	public JSONObject getUserOwnerships(String username){
		
		if(userDao.isUserExist(username) == true){
			List<Ownership> ownerships = ownershipDao.getUserOwnerships(username);
			JSONObject jsonObject = ownershipJson(ownerships);
			
			try {
				jsonObject.put("success","true");
			} catch (JSONException e) {
				e.printStackTrace();
			}
			
			return jsonObject;
		}
		else return getSuccess(false,utils.getMessage(utils.NO_USER),null);
	}
	
	// User
	public JSONObject getUserData(String username){
		User user = userDao.getUser(username);
		JSONObject userOwnership = getUserOwnerships(username);
		
		JSONObject json = new JSONObject();
		JSONObject jsonResult = new JSONObject();
		
		if(user == null) return getSuccess(false, utils.getMessage(utils.NO_USER),null);
		
		try {
			json.put("id",user.getId());
			json.put("username",user.getUsername());
			json.put("credits",user.getCredits());
			json.put("ownerships",userOwnership.get("ownerships"));
			jsonResult.put("user",json);
			jsonResult.put("success","true");
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return jsonResult;
		
	}
	
	public JSONObject getUserDataForLogin(String username) throws JSONException{
		boolean userExist = gameServices.isUserExist(username);
		
		JSONObject result = getSuccess(userExist,utils.getMessage(utils.NO_USER),null);
		if(userExist == true) {
			result.put("user",getUserData(username).get("user"));
			result.put("itemstobuy",getItemList().get("itemstobuy"));
		}
		
		return result;
	}
	
	// Items
	public JSONObject getItemList(){
		List <Item> itemList =  itemDao.getItems();
		JSONObject jsonResult = new JSONObject();
		JSONArray itemArray = new JSONArray();
	
		try {		
			for(Item item:itemList){
				JSONObject json = new JSONObject();
				json.put("itemname",item.getItemName());
				json.put("name",item.getItem());
				json.put("price",item.getPrice());
				json.put("type",item.getType());
				
				itemArray.put(json);
			}
			jsonResult.put("itemstobuy",itemArray);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return jsonResult;
	}
	
	// Aircrafts
	
	public JSONObject getFuelOfAircraft(String ownershipId){
		try {
			if(ownershipDao.getOwnership(Integer.parseInt(ownershipId)) == null) return getSuccess(false,utils.getMessage(utils.NO_OWNERSHIP_WITH_ID),null);
			
			int fuel = flightServices.getFuelOfAircraft(Integer.parseInt(ownershipId));
			
			if(fuel != -1){
				JSONObject json = new JSONObject();
				json.put("id", ownershipId);
				json.put("fuel",fuel);
				json.put("success","true");
				return json;
			}
			else return getSuccess(false, utils.getMessage(utils.NOT_AN_AIRCRAFT),null);
		} catch (JSONException e) {
			
			e.printStackTrace();
		}
		catch (NumberFormatException e) {
			return getSuccess(false, utils.getMessage(utils.INVALID_NUMBER_FORMAT),null);
		}
		
		return getSuccess(true, "",null);
		
	}
	
	// Messages
	public JSONObject getUserMessages(String username){
		User user = userDao.getUser(username);
		JSONObject jsonResult = new JSONObject();
		if(user == null) return getSuccess(false, utils.getMessage(utils.NO_USER),null);
		
		JSONArray messagesArray = new JSONArray();
		List<Message> messages = messageDao.getMessagesOfUser(user);

		try{
			for(Message message : messages){
				JSONObject json = new JSONObject();
				String sendUser;
				if(message.isFlightmsg() == false) sendUser = userDao.getUserWithId(message.getSendid()).getUsername();
				else sendUser = ownershipDao.getOwnership(message.getSendid()).getUsername();
				
				json.put("from",sendUser);
				json.put("msg",message.getMessage());
				json.put("isflight",message.isFlightmsg());
				json.put("date",message.getDate());
				
				messageDao.deleteMessage(message);
				
				messagesArray.put(json);
			}
		jsonResult.put("messages",messagesArray);	
			
		}catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return jsonResult;
		
	}
	
	
	// Local
	
	private JSONObject airportsJson(List<Airport> airports){
		JSONArray airportsArray = new JSONArray();
		JSONObject airportsJson = new JSONObject();
		try {
			for(Airport airport: airports){
				JSONObject json = new JSONObject();
				json.put("id", airport.getId());
				json.put("airportcode",airport.getAirportCode());
				json.put("airportname",airport.getAirportName());
				json.put("lat",airport.getLat());
				json.put("lon",airport.getLon());
				
				airportsArray.put(json);
			}
			airportsJson.put("airports",airportsArray);
		} catch (Exception e) {
			
		}
		return airportsJson;
	}
	
	private JSONObject ownershipJson(List<Ownership> ownerships){
		JSONArray ownershipArray = new JSONArray();
		JSONObject ownershipJson = new JSONObject();
		
		try {
			for(Ownership ownership : ownerships){
				JSONObject json = new JSONObject();
				json.put("id",ownership.getId());
				json.put("username",ownership.getUsername());
				json.put("itemname",ownership.getItemname());
				json.put("lat",ownership.getLat());
				json.put("lon",ownership.getLon());
				json.put("airportcode",ownership.getAirportcode());
				json.put("type",itemDao.getItem(ownership.getItemname()).getType());
				ownershipArray.put(json);
			}
			
			ownershipJson.put("ownerships",ownershipArray);
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}
		
		return ownershipJson;
	}
	
}
